#include <tchar.h>
#include <windows.h>
#include <strsafe.h>

#define SNARL_STRING_LENGTH 1024

typedef enum {
	M_ABORTED         = 0x80000007,
	M_ACCESS_DENIED   = 0x80000009,
	M_ALREADY_EXISTS  = 0x8000000C,
	M_BAD_HANDLE      = 0x80000006,
	M_BAD_POINTER     = 0x80000005,
	M_FAILED          = 0x80000008,
	M_INVALID_ARGS    = 0x80000003,
	M_NO_INTERFACE    = 0x80000004,
	M_NOT_FOUND       = 0x8000000B,
	M_NOT_IMPLEMENTED = 0x80000001,
	M_OK              = 0x00000000,
	M_OUT_OF_MEMORY   = 0x80000002,
	M_TIMED_OUT       = 0x8000000A
} M_RESULT;

typedef enum {
	SNARL_SHOW = 1,
	SNARL_HIDE,
	SNARL_UPDATE,
	SNARL_IS_VISIBLE,
	SNARL_GET_VERSION,
	SNARL_REGISTER_CONFIG_WINDOW,
	SNARL_REVOKE_CONFIG_WINDOW,
	SNARL_REGISTER_ALERT,
	SNARL_REVOKE_ALERT,
	SNARL_REGISTER_CONFIG_WINDOW_2,
	SNARL_GET_VERSION_EX,
	SNARL_SET_TIMEOUT,
	SNARL_EX_SHOW = 0x20
} SNARL_COMMANDS;

typedef struct SNARLSTRUCT {
    SNARL_COMMANDS cmd;
    int id;
    int timeout;
    int lngData2;
    char title[SNARL_STRING_LENGTH];
    char text[SNARL_STRING_LENGTH];
    char icon[SNARL_STRING_LENGTH];
} SNARLSTRUCT;

typedef struct SNARLSTRUCTEX {
    SNARL_COMMANDS cmd;
    int id;
    int timeout;
    int lngData2;
    char title[SNARL_STRING_LENGTH];
    char text[SNARL_STRING_LENGTH];
    char icon[SNARL_STRING_LENGTH];
    char class[SNARL_STRING_LENGTH];
    char extra[SNARL_STRING_LENGTH];
    char extra2[SNARL_STRING_LENGTH];
    int reserved1;
    int reserved2;
} SNARLSTRUCTEX;

HWND m_hwndFrom;

int snarl_show_message(char *title, char *message, int timeout);
int snarl_send(struct SNARLSTRUCT ss);
HWND snarl_get_window();

int snarl_show_message(char *title, char *message, int timeout)
{
	LPCSTR snarl_title;
	LPCSTR snarl_message;
	int snarl_timeout;
	LPCSTR snarl_iconpath = "";
	HWND hWndReply = NULL;
    WPARAM uReplyMsg = 0;
	SNARLSTRUCT ss;

	snarl_title = (LPCSTR)(LPCTSTR) title;
	snarl_message = (LPCSTR)(LPCTSTR) message;
	snarl_timeout = timeout;

	ZeroMemory((void*)&ss, sizeof(ss));

	ss.cmd = SNARL_SHOW;
	StringCbCopyA((LPSTR)&ss.title, SNARL_STRING_LENGTH, snarl_title);
	StringCbCopyA((LPSTR)&ss.text,  SNARL_STRING_LENGTH, snarl_message);
	StringCbCopyA((LPSTR)&ss.icon,  SNARL_STRING_LENGTH, snarl_iconpath);
	ss.timeout = snarl_timeout;

	ss.lngData2 = (long) hWndReply;
	ss.id = uReplyMsg;
	return snarl_send(ss);
}

int snarl_send(struct SNARLSTRUCT ss)
{
	DWORD result = M_FAILED;
	HWND hWnd = snarl_get_window();
	if (IsWindow(hWnd))
	{
		COPYDATASTRUCT cds;
		cds.dwData = 2;
		cds.cbData = sizeof(ss);
		cds.lpData = &ss;
		if (!SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM) m_hwndFrom, (LPARAM) &cds, SMTO_NORMAL, 1000, &result))
		{
			result = M_TIMED_OUT;
		}
	}
	return result;
}

HWND snarl_get_window()
{
	return FindWindow(NULL, _T("Snarl"));
}